#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <wait.h>
#include <pthread.h>

class Prama
{
  public:
  int port;
  std::string ip;
  int sock;
  Prama(int _port,std::string _ip,int _sock)
    :port(_port),ip(_ip),sock(_sock)
  {}
  ~Prama()
  {}
};

class TcpServer
{
  private:
    int port;
    int lsock;
  public:
    TcpServer(int _port):port(_port),lsock(-1)
   {}
    ~TcpServer()
    {
      if(lsock>=0)close(lsock);
    }

    void InitTcpServer()
    {
      lsock=socket(AF_INET,SOCK_STREAM,0);
      if(lsock<0)
      {
        std::cerr<<"socket error"<<std::endl;
        exit(2);
      }

      struct sockaddr_in local;
      local.sin_family=AF_INET;
      local.sin_port=htons(port);
      local.sin_addr.s_addr=INADDR_ANY;
      socklen_t len=sizeof(local);
      if(bind(lsock,(struct sockaddr*)&local,len)<0)
      {
        std::cerr<<"bind error"<<std::endl;
        exit(3);
      }

      if(listen(lsock,5)<0)
      {
        std::cerr<<"listen error"<<std::endl;
        exit(4);
      }

      std::cout<<"server started..."<<std::endl;
    }

  static void* HandlerRequest(void* arg)
    {
      Prama *p=(Prama*)arg;
      pthread_detach(pthread_self());

      Sercive(p->sock,p->ip,p->port);
      close(p->sock);
      delete p;
      return nullptr;
    }
    void Loop()
    {
      //signal(SIGCHLD,SIG_IGN);//fork后父进程忽略子进程，不用父进程等待
      struct sockaddr_in peer;
      for(;;)
      {
         socklen_t len=sizeof(peer);
        int sock=accept(lsock,(struct sockaddr*)&peer,&len);
        if(sock<0)
        {
          std::cerr<<"accept error"<<std::endl;
          continue;
        }
        
        std::string ip=inet_ntoa(peer.sin_addr);
        int _port=ntohs(peer.sin_port);
        
        pthread_t tid;
        Prama *p=new Prama(_port,ip,sock);
        pthread_create(&tid,nullptr,HandlerRequest,p);


    /*    pid_t id=fork();
        if(id==0)
        {
          if(fork()>0)
          {
            exit(0);//爸爸进程直接退出
          }
          std::cout<<ip<<':'<<_port<<" 连接成功"<<std::endl;//孙子进程由系统接管 回收资源
          Sercive(sock,ip,_port);
          exit(0);
        }
        close(sock);//爷爷进程关闭文件描述符 与客户端断开联系
        waitpid(-1,nullptr,0);
    */
        }
    
    }

   static void Sercive(int sock,std::string ip,int port)
    {
      char buff[1024];
      while(true)
      {
        ssize_t size=read(sock,buff,sizeof(buff));
        if(size>0)
        {
          buff[size]=0;
          std::cout<<ip<<':'<<port<<'#'<<buff<<std::endl;

          write(sock,buff,size);
        }else if(size==0)
        {
          std::cout<<ip<<":"<<port<<"退出"<<std::endl;
          break;
        }else{
          std::cerr<<ip<<':'<<port<<':'<<sock<<" read error"<<std::endl;
          break;
        }
      }
      std::cout<<"sercive don"<<std::endl;
    }
};
